package cn.boodqian.airreport;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import junit.framework.Assert;

import com.google.gson.*;

import cn.boodqian.utils.*;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.appwidget.AppWidgetManager;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.MenuItem;

public class LocationSelectActivity extends SherlockActivity implements TextWatcher, OnItemClickListener {
	private class GAEHandler extends Handler {
		private String message = getString(R.string.refresh_location);
		private void updateDlgMessage(String text) {
			Assert.assertNotNull(mDlg);
			mDlg.setMessage( message + "\n" + text );
		}
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what) {
			case GAERequest.MESSAGE_DNS:
				updateDlgMessage( getString(R.string.gae_message_dns) );
				break;
			case GAERequest.MESSAGE_QUERY:
				updateDlgMessage(
						String.format( getString(R.string.gae_message_query), msg.arg1, msg.arg2));
				break;
			case GAERequest.MESSAGE_DONE_OK:
				newLocationArrived((String)msg.obj);
				Toast.makeText(
						LocationSelectActivity.this,
						getString( R.string.refresh_done ),
						Toast.LENGTH_LONG).show();
				try {
				    mDlg.dismiss();
				    mDlg = null;
				} catch( Exception e ) {
				    // In case activity finished before dismiss (several hits seen in crash report)
				    Log.w( "Dismiss exception: " + e.getLocalizedMessage() );
				}
				break;
			case GAERequest.MESSAGE_DONE_ERR:
				Toast.makeText(
						LocationSelectActivity.this,
						getString(R.string.refresh_error) + "\n"
								+ mGAERequest.getLastError(),
								Toast.LENGTH_LONG).show();
				try {
				    mDlg.dismiss();
				    mDlg = null;
				 } catch( Exception e ) {
				     // In case activity finished before dismiss (several hits seen in crash report)
				     Log.w( "Dismiss exception: " + e.getLocalizedMessage() );
				 }
				break;
			case GAERequest.MESSAGE_RUNNING:
				Toast.makeText(
						LocationSelectActivity.this,
						getString(R.string.refresh_running),
						Toast.LENGTH_LONG).show();
				break;
			case GAERequest.MESSAGE_START:
				mDlg = ProgressDialog.show(
						LocationSelectActivity.this,
						getString(R.string.refresh_wait),
						message, true);
				break;
			}
		}
	}
	
	private Gson mGson = new GsonBuilder().setDateFormat(DateFormat.FULL, DateFormat.FULL).create();
	private Handler handler = new Handler();
	private ListView mListLocation;
	private Drawable searchIcon;
	private EditText mEditSearch; 
	private MySimpleAdapter mSearchAdapter = null;
	private Thread mLocationCodeThd = null;
	private GAERequest mGAERequest = null;
	private GAERequest mSilentGAERequest = new GAERequest(GlobalData.gGAEProject);
	private ProgressDialog mDlg = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.location_select);

		ActionBar actionBar = getSupportActionBar();
		actionBar.setDisplayHomeAsUpEnabled(true);
		
		mGAERequest = new GAERequest(GlobalData.gGAEProject, new GAEHandler());
		
		mListLocation = (ListView) findViewById(R.id.list_location);
		mEditSearch = (EditText) findViewById(R.id.edit_search);
		
		mEditSearch.addTextChangedListener(this);
		mListLocation.setOnItemClickListener(this);

		searchIcon = getResources().getDrawable(android.R.drawable.ic_menu_search);
		mEditSearch.post(new Runnable() {
			public void run() {
				android.text.TextPaint paint = mEditSearch.getPaint();
				android.widget.RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams)mEditSearch.getLayoutParams();
				Log.i(String.format(java.util.Locale.US, "%f,%d,%d,%d", -paint.ascent() + paint.descent(), mEditSearch.getHeight(),  lp.bottomMargin, lp.topMargin));
				int size = mEditSearch.getHeight()-lp.bottomMargin-lp.topMargin;
				searchIcon.setBounds(0, 0, size, size);
				mEditSearch.setCompoundDrawables(null, null, searchIcon, null);
			}
		});
		
		GlobalData.restoreLocationPrefs(this);
	}

	private void updateLocationListUI()
	{
		if(GlobalData.gLocationList == null) {
			Log.w("GlobalData.gLocationList is null");
			return;
		}
		
		mSearchAdapter = new MySimpleAdapter(this, GlobalData.gLocationList,
				R.layout.location_select_item, new String[]{"city", "name", "address", "tip"},
				new int[]{R.id.text_city, R.id.text_name, R.id.text_address, R.id.text_tip});
		mListLocation.setAdapter(mSearchAdapter);
	}
	
	private void newLocationArrived(String newLocationStr) {
		GlobalData.gLocationList = null;
		JsonParser parser = new JsonParser();
		try {
			JsonArray array = parser.parse(newLocationStr).getAsJsonArray();
			GlobalData.gLocationList = new ArrayList<HashMap<String,String>>();
			for(JsonElement e:array) {
				HashMap<String, String> map = mGson.fromJson(e, HashMap.class);
				GlobalData.gLocationList.add(map);
			}
		} catch (Exception e) {
			GlobalData.gLocationList = null;
			e.printStackTrace();
			Log.e(e.getLocalizedMessage());
			Toast.makeText(
					this,
					getString(R.string.data_format_error),
					Toast.LENGTH_LONG).show();
		}
	}
	
	private void updateLocationList(final Runnable run)
	{
		// Location info already there
		Log.i("" + GlobalData.gLocationNeedUpdate);
		if ( GlobalData.gLocationList != null && GlobalData.gLocationList.size() > 0 &&
				!GlobalData.gLocationNeedUpdate ) {
			run.run();
			return;
		}

		OnClickListener listener = new OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				final String lang =
						((which == DialogInterface.BUTTON_POSITIVE) ?
								"zh" : "en");
				// Use thread to prevent any possible UI freezes
				Thread thd = new Thread() {
					@Override
					public void run() {
						mGAERequest.doGet("/location/list?lang=" + lang);
						handler.post(new Runnable() {
							@Override
							public void run() {
								GlobalData.gLocationNeedUpdate = false;
								if (run != null)
									run.run();
							}
						});
					}
				};
				thd.start();
			}
		};
		
		String locale = Locale.getDefault().getLanguage();
		if( ! locale.startsWith("zh") ) {
			new AlertDialog.Builder(this).setTitle(android.R.string.dialog_alert_title)
					.setMessage(R.string.use_chinese)
					.setPositiveButton(android.R.string.yes, listener)
					.setNegativeButton(android.R.string.no, listener)
					.show();
		} else {
			listener.onClick(null, DialogInterface.BUTTON_POSITIVE);
		}

	}

	@Override
	public void afterTextChanged(Editable s) {
		if( mSearchAdapter == null ) return;
		mSearchAdapter.getFilter().filter(s.toString());
	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count,
			int after) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		HashMap<String,String> map = (HashMap<String, String>)parent.getItemAtPosition(position);
		switch(parent.getId()) {
		case R.id.list_location:
			int widgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
			Intent oldintent = getIntent();
			Bundle extras = oldintent.getExtras();
			if (extras != null) {
				widgetId = extras.getInt(
						AppWidgetManager.EXTRA_APPWIDGET_ID, 
						AppWidgetManager.INVALID_APPWIDGET_ID);
			}
			String locId = map.get("id");
			String locName = map.get("name");
			Intent intent = new Intent();
			intent.putExtra("id", locId);
			if( widgetId != AppWidgetManager.INVALID_APPWIDGET_ID ) {
				// If it's started from widget, need to set the widget ID
				intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
				AirreportWidgetProvider.saveWidgetPref(this, widgetId, locId, locName);

				// Then update the widget
				Intent intent2 = new Intent(this, AirreportWidgetProvider.class);
				intent2.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
				intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{widgetId});
				sendBroadcast(intent2);
			}
			setResult(RESULT_OK, intent);
			finish();
			break;
		default:
			assert(false);	
		}
	}
	
	@Override
	public void onStart() {
		super.onStart();
		
		// Location version check
		if( mLocationCodeThd==null && !GlobalData.gLocationNeedUpdate ) {
			mLocationCodeThd = new Thread() {
				@Override
				public void run() {
					try {
						// Use private, don't want being notified about progresses
						String str = mSilentGAERequest.doGet("/location/code");
						int newLocationCode = mGson.fromJson(str, int.class);
						if( GlobalData.gLastLocationCode != newLocationCode )
						{
							Log.i("location need update: old/new = " +
									GlobalData.gLastLocationCode + "/" +
									newLocationCode );
							GlobalData.gLocationNeedUpdate = true;
							GlobalData.gLastLocationCode = newLocationCode;
							LocationSelectActivity.this.runOnUiThread(new Runnable()
							{
							    public void run()
							    {
							        Toast.makeText(
							                LocationSelectActivity.this,
							                getString( R.string.new_location_list ),
							                Toast.LENGTH_LONG).show();
							    }
							});
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					mLocationCodeThd = null;
				}
			};
			mLocationCodeThd.start();
		}
		
		// Update location list if necessary
		updateLocationList(new Runnable() {
			@Override
			public void run() {
				updateLocationListUI();
			}
		});
	}

	@Override
	protected void onStop() {
		super.onStop();
		
		GlobalData.saveLocationPrefs(this);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    switch (item.getItemId()) {
	    case android.R.id.home:
	        // app icon in action bar clicked; go home
	        finish();
	        return true;
	    default:
	        return super.onOptionsItemSelected(item);
	    }
    }
}
